from config import ModelLayers, Config
from log import log
from dao.model_describedaao import ModelDescribeDao
from entity.model_describe import ModelDescribe
from model_layers import layer_dict
from keras.applications import *


class ModelListUtil:
    def __init__(self):
        self.md = ModelDescribeDao()

    @staticmethod
    def check(model_list: list, models: list = None):
        if len(model_list) == 0:
            log.error("模型层数为0")
            raise RuntimeError("模型层数为0")
        for idx, model_list_line in enumerate(model_list):

            if len(model_list_line) < 1:
                log.error("传入参数不足")
                raise RuntimeError("传入参数不足")
            layer = layer_dict.get(model_list_line[0])
            headable = layer().check(model_list_line, models)
            if idx == 0 and not headable:
                raise RuntimeError("使用了不可谓头的层为头")
        log.debug("model_list经检查无措")

    def model_list_to_db(self, model_list: list, train_id: int):
        ModelListUtil.check(model_list)
        for idx, model_list_line in enumerate(model_list):
            layer = layer_dict.get(model_list_line[0])
            m = layer().persistence(model_list_line, train_id)
            self.md.setAll(m)

    @staticmethod
    def get_model_list_from_db(train_id: int):
        md = ModelDescribeDao()
        model_tuple = md.findAllByTrainId(train_id)
        log.debug(model_tuple)
        model_list = []
        for index, value in enumerate(model_tuple):
            line = value[1:]
            if index == 0:  # 初始化层
                if line[0] == ModelLayers.ConvBase:
                    trainable = False if line[3] == '0' else True
                    trainable_num = int(line[4])
                    # clazz = line[2]
                    clazz = globals()[line[2]]
                    log.debug(clazz)
                    model_list.append([line[0], clazz, trainable, trainable_num, line[5]])
                elif line[0] == ModelLayers.Conv2D:
                    model_list.append([line[0], int(line[2]), int(line[3]), True if line[4] == '1' else False])
                elif line[0] == ModelLayers.Concatenate:
                    model_list.append([line[0]])
                elif line[0] == ModelLayers.Average:
                    model_list.append([line[0]])
                elif line[0] == ModelLayers.Maximum:
                    model_list.append([line[0]])
                else:
                    raise RuntimeError("未知初始化层类型，检查数据库数据")
            else:
                if line[0] == ModelLayers.Conv2D:
                    model_list.append([line[0], int(line[2]), int(line[3]), True if line[4] == '1' else False])
                elif line[0] == ModelLayers.Activation:
                    model_list.append([line[0], line[2]])
                elif line[0] == ModelLayers.MaxPooling2D:
                    model_list.append([line[0], int(line[2])])
                elif line[0] == ModelLayers.Dropout:
                    model_list.append([line[0], float(line[2])])
                elif line[0] == ModelLayers.Flatten:
                    model_list.append([line[0]])
                elif line[0] == ModelLayers.Dense:
                    model_list.append([line[0], int(line[2]), line[3]])
                elif line[0] == ModelLayers.BatchNormalization:
                    model_list.append([line[0]])
                else:
                    raise RuntimeError("未知层id或者将conv_base用在非初始化层，检查数据库")
            log.debug(line)
            log.debug(model_list)
        return model_list


if __name__ == "__main__":
    model_list = ModelListUtil().get_model_list_from_db(504)
    for i in model_list:
        print(i)
    # model_list = [
    #     # [ModelLayers.Flatten],
    #     [ModelLayers.ConvBase, InceptionV3, True],
    #     [ModelLayers.Conv2D, 64, 3, True],
    #     [ModelLayers.Flatten],
    #     [ModelLayers.Dense, 128],
    #     [ModelLayers.BatchNormalization],
    #     [ModelLayers.Dense, 64],
    #     [ModelLayers.BatchNormalization],
    #     [ModelLayers.Dense, 32],
    #     [ModelLayers.Dropout, 0.5],
    #     [ModelLayers.BatchNormalization],
    # ]
    # ModelListUtil.check(model_list)
    # ModelListUtil().model_list_to_db(model_list,293)
